package il.ac.tau.cvws.scrabblesidekick.server.engine.recoginition.common.squareiter;

import il.ac.tau.cvws.scrabblesidekick.server.engine.recoginition.calibration.common.CalibrationConstants;
import il.ac.tau.cvws.scrabblesidekick.server.util.cv.CvUtil;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.Board;

import com.googlecode.javacv.cpp.opencv_core.IplImage;

/* Iterates over the Scrabble board and crops its squares. Each square is then
 * passed to the given callback for handling. The calibration and game engines
 * both use this class to iterate over the board, but they handle it differently. 
 */
public class SquareCropper
{
	private boolean withBevel;
	
	public SquareCropper()
	{
		this(true);
	}
	
	public SquareCropper(boolean withBevel)
	{
		this.withBevel = withBevel;
	}
	
	public void crop(IplImage boardImage, Callback callback)
	{
		handleCropping(boardImage, callback, withBevel);
	}
	
	public void handleCropping(IplImage boardImage, Callback callback, boolean withBevel)
	{
		double width  = boardImage.width();
		double height = boardImage.height();
		
		int bevel = ((int)((width / Board.SQUARES_NUM) * (withBevel ? CalibrationConstants.SQUARE_CROP_BEVEL_RATIO : 0.0)));
		int actualSquareNum = Board.SQUARES_NUM + (withBevel ? 2 : 0);
		
		for (int row = 0; row < Board.SQUARES_NUM; row++)
		{
			for (int col = 0; col < Board.SQUARES_NUM; col++)
			{
				int x1 = (int)((width * (col + 1)) / actualSquareNum) - bevel;
				int x2 = (int)((width * (col + 2)) / actualSquareNum) + bevel;
				int y1 = (int)((height * (row + 1)) / actualSquareNum) - bevel;
				int y2 = (int)((height * (row + 2)) / actualSquareNum) + bevel;
				
				IplImage rawSquareImage = CvUtil.cropImage(boardImage, x1, y1, x2 - x1, y2 - y1);
				IplImage squareThresholdImage = CvUtil.createThresholdImage(rawSquareImage, 0.5);
				
				/* After cropping the square, pass it to the callback for handling.
				 */
				callback.handleSquare(this, squareThresholdImage, row, col);
			}
		}
	}
	
	public static interface Callback
	{
		public void handleSquare(SquareCropper cropper, IplImage squareImage, int row, int col);
	}
}
